﻿using System;
using System.Configuration.Install;
using System.IO;
using System.Reflection;
using System.ServiceProcess;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ServiceOperation
{
    public partial class MainFrom : Form
    {
        public MainFrom()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 浏览（打开文件）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnBrowser_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "(*.exe)|*.exe";
            openFileDialog1.FileName = "";
            openFileDialog1.Title = "选择Windows服务";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                SetValue(txtPath, openFileDialog1.FileName);
            }
        }

        /// <summary>
        /// 安装
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnInstall_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                if (!Vaild())
                {
                    return;
                }
                try
                {
                    string[] cmdline = { };
                    string serviceFileName = txtPath.Text.Trim();
                    string serviceName = GetServiceName(serviceFileName);
                    if (string.IsNullOrEmpty(serviceName))
                    {
                        SetValue(txtTip, "指定文件不是Windows服务！");
                        return;
                    }
                    if (ServiceIsExisted(serviceName))
                    {
                        SetValue(txtTip, "要安装的服务已经存在！");
                        return;
                    }
                    SetValue(txtTip, "服务安装中...");
                    TransactedInstaller transactedInstaller = new TransactedInstaller();
                    AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
                    assemblyInstaller.UseNewContext = true;
                    transactedInstaller.Installers.Add(assemblyInstaller);
                    transactedInstaller.Install(new System.Collections.Hashtable());
                    SetValue(txtTip, "服务安装成功！");
                }
                catch (Exception ex)
                {
                    SetValue(txtTip, ex.Message);
                }
            });

        }

        /// <summary>
        /// 运行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRun_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                if (!Vaild())
                {
                    return;
                }
                try
                {
                    string serviceName = GetServiceName(txtPath.Text.Trim());
                    string[] paramsString = textBoxStartParams.Text.Split(new char[] { ',' });

                    if (string.IsNullOrEmpty(serviceName))
                    {
                        SetValue(txtTip, "指定文件不是Windows服务！");
                        return;
                    }

                    if (!ServiceIsExisted(serviceName))
                    {
                        SetValue(txtTip, "要运行的服务不存在！");
                        return;
                    }
                    ServiceController service = new ServiceController(serviceName);
                    if (service.Status != ServiceControllerStatus.Running && service.Status != ServiceControllerStatus.StartPending)
                    {
                        if (paramsString.Length > 0)
                        {
                            service.Start(paramsString);
                        }
                        else
                        {
                            service.Start();
                        }
                        SetValue(txtTip, "服务运行成功！");
                    }
                    else
                    {
                        SetValue(txtTip, "服务正在运行！");
                    }
                }
                catch (Exception ex)
                {
                    SetValue(txtTip, ex.Message);
                }
            });
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                if (!Vaild())
                {
                    return;
                }
                try
                {
                    string[] cmdline = { };
                    string serviceFileName = txtPath.Text.Trim();
                    string serviceName = GetServiceName(serviceFileName);
                    if (string.IsNullOrEmpty(serviceName))
                    {

                        SetValue(txtTip, "指定文件不是Windows服务！");
                        return;
                    }
                    if (!ServiceIsExisted(serviceName))
                    {
                        SetValue(txtTip, "要停止的服务不存在！");
                        return;
                    }
                    ServiceController service = new ServiceController(serviceName);
                    if (service.Status == ServiceControllerStatus.Running)
                    {
                        service.Stop();
                        service.Dispose();
                        SetValue(txtTip, "服务停止成功！");
                    }
                    else
                    {
                        SetValue(txtTip, "服务已经停止！");
                    }

                }
                catch (Exception ex)
                {
                    SetValue(txtTip, ex.Message);
                }
            });
        }

        /// <summary>
        /// 卸载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUninstall_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                if (!Vaild())
                {
                    return;
                }
                try
                {
                    string serviceFileName = txtPath.Text.Trim();
                    string serviceName = GetServiceName(serviceFileName);
                    if (string.IsNullOrEmpty(serviceName))
                    {
                        SetValue(txtTip, "指定文件不是Windows服务！");
                        return;
                    }
                    if (!ServiceIsExisted(serviceName))
                    {
                        SetValue(txtTip, "要卸载的服务不存在！");
                        return;
                    }
                    try
                    {
                        SetValue(txtTip, "服务卸载中...");
                        string[] cmdline = { };
                        TransactedInstaller transactedInstaller = new TransactedInstaller();
                        AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
                        transactedInstaller.Installers.Add(assemblyInstaller);
                        transactedInstaller.Uninstall(null);
                        SetValue(txtTip, "卸载服务[" + serviceName + "]成功！");
                    }
                    catch (Exception ex)
                    {
                        SetValue(txtTip, "卸载服务[" + serviceName + "]出现错误:" + ex.Message);
                    }
                }
                catch (Exception ex)
                {
                    SetValue(txtTip, ex.Message);
                }
            });
        }

        /// <summary>
        /// 获取Windows服务的名称
        /// </summary>
        /// <param name="serviceFileName">文件路径</param>
        /// <returns>服务名称</returns>
        private string GetServiceName(string serviceFileName)
        {
            try
            {
                Assembly assembly = Assembly.LoadFrom(serviceFileName);
                Type[] types = assembly.GetTypes();
                foreach (Type myType in types)
                {
                    if (myType.IsClass && myType.BaseType == typeof(Installer))
                    {
                        FieldInfo[] fieldInfos = myType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Default | BindingFlags.Instance | BindingFlags.Static);
                        foreach (FieldInfo myFieldInfo in fieldInfos)
                        {
                            if (myFieldInfo.FieldType == typeof(ServiceInstaller))
                            {
                                ServiceInstaller serviceInstaller = (ServiceInstaller)myFieldInfo.GetValue(Activator.CreateInstance(myType));
                                return serviceInstaller.ServiceName;
                            }
                        }
                    }
                }
                return "";
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 判断服务是否已经存在
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>bool</returns>
        private bool ServiceIsExisted(string serviceName)
        {
            ServiceController[] services = ServiceController.GetServices();
            foreach (ServiceController s in services)
            {
                if (s.ServiceName == serviceName)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 操作前校验
        /// </summary>
        /// <returns></returns>
        private bool Vaild()
        {
            if (string.IsNullOrEmpty(txtPath.Text.Trim()))
            {
                SetValue(txtTip, "请先选择Windows服务路径！");
                return false;
            }

            if (!File.Exists(txtPath.Text.Trim()))
            {
                SetValue(txtTip, "路径不存在");
                return false;
            }

            if (!txtPath.Text.Trim().EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
            {
                SetValue(txtTip, "所选文件不是Windows服务");
                return false;
            }

            return true;
        }


        /// <summary>
        /// 设置值
        /// </summary>
        /// <param name="textBox"></param>
        /// <param name="msg"></param>
        private void SetValue(TextBox textBox, string msg)
        {
            BeginInvoke(new Action(() =>
            {
                textBox.Text = msg;
            }));
        }
    }
}
